package fpzhan.plane.program.param;

import fpzhan.plane.program.exception.ExecuteParamToolException;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

public abstract class ParamTool<T> {

    protected String getKey;

    protected Operate operate;



    protected ParamTool(String getKey, Supplier<T> supplier) throws ExecuteParamToolException {
        if (getKey == null && supplier == null) {
            throw new ExecuteParamToolException();
        }
        this.operate=new Operate(new ArrayList<>(),new ArrayList<>(),new ArrayList<>(),new ArrayList<>());
        if (getKey != null) {
            this.getKey = getKey;
        }
        if (supplier != null) {
            operate.add(Supplier.class.getName(),supplier,null);
        }
    }

    protected ParamTool(String getKey, Operate operate) {
        this.getKey = getKey;
        this.operate = operate;
    }

    public  abstract  <E> ParamTool<E> then(Function<T,E> function);

    public abstract  <R,E> ParamTool<E> then(BiFunction<T,R,E> biFunction,R r);

    public abstract  <E,R> ParamTool<E> thenLink(BiFunction<T,R,E> biFunction,String key);

    protected abstract Object end();

    public Operate getOperate() {
        return operate;
    }

    protected class Operate{

        final private List<String> functionTypes;

        final private List<Object> chains;

        final private List<Object> params ;

        final private List<String> links;

        public Operate(List<Object> chains, List<Object> params, List<String> links, List<String> functionTypes) {
            this.chains = chains;
            this.params = params;
            this.links = links;
            this.functionTypes=functionTypes;
        }

        public void add(String functionType,Object chain , Object param, String link){
            functionTypes.add(functionType);
            chains.add(chain);
            params.add(param);
            links.add(link);
        }

        public void add(String functionType,Object chain ,Object param){
            add(functionType,chain,param,null);
        }

        public List<String> getFunctionTypes() {
            return functionTypes;
        }

        public List<Object> getChains() {
            return chains;
        }

        public List<Object> getParams() {
            return params;
        }

        public List<String> getLinks() {
            return links;
        }
    }

}
